﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace UnitConversionLib.Example
{
    class Program
    {
        static void Main(string[] args)
        {
            Ex2();
            Console.WriteLine("==== ex1, working with units");
            Console.WriteLine("Checking the Newton (N) unit of force.");

            Unit unt0 = Unit.GetRegisteredUnit("N");                    //From registered library

            var str2 = "N";
            var str3 = "kg*m/sec^2";
            var str4 = "kg*m/s^(ton/kg/500)";
            var str5 = "kg*m/s^(kg/kg*2)";


            Unit unt1 = Unit.Parse("N");        //Parsing from string - simple format
            Unit unt2 = str2;                   //Explicit conversion
            Unit unt3 = Unit.Parse(str3);       //Parsing from string - from expression (1)
            Unit unt4 = Unit.Parse(str4);       //Parsing from string - from expression (2)
            Unit unt5 = Unit.Parse(str5);       //Parsing from string - from expression (3)
            Unit unt6 = Unit.Parse("kg*m") / (Unit.Parse("sec") ^ 2);   //Parsing from string - from expression (4)

            Console.WriteLine();
            Console.WriteLine("- {0} {1} equal to {2}", unt1, unt1 == unt2 ? "is" : "is not", unt2);
            Console.WriteLine();

            Console.WriteLine("- {0} {1} even equal to these:\n\t{3},\n\t{4},\n\t{5}",unt1, (unt1 == unt2 && unt1 == unt3 && unt1 == unt4 & unt1 == unt5) ? "is" : "is not", str2, str3, str4, str5);

            var kmph = Unit.Parse("km/hour");
            Unit.Register(ref kmph, "kmph");
            var D = Measurable.Parse("100 km");
            var T = Measurable.Parse("60 min");

            Console.WriteLine("");
            Console.WriteLine("==== ex2, the driving car");
            Console.WriteLine("Consider a car who was drived about 100 km in 60 min (D = '{0}',T = '{1}')", D, T);

            Console.WriteLine("it can be said the car also is derived '{0:0.00}' in '{1:0.0}'", D.ConvertTo("mi"), T.ConvertTo("hour"));
            Console.WriteLine("or even '{0:0.00}' in '{1:0.0}'", D.ConvertTo("foot"), T.ConvertTo("sec"));
            var avgSpeed = D/T;
            Console.WriteLine("Finally the average speed is D/T='{0:0.0}'='{1:0.0}'='{2:0.0}'", avgSpeed, avgSpeed.ConvertTo("km / hour"), avgSpeed.ConvertTo("kmph"));

            Console.WriteLine("");
            Console.WriteLine("** Check the code of this console application for more samples (check the code inside CodeExample() method)...");

            Console.ReadKey();
        }

        static void CodeExample()
        {
            //Creating and parsing units
            Unit unt0 = Unit.GetRegisteredUnit("N");                    //From registered library
            Unit unt1 = Unit.Parse("N");                                //Parsing from string - simple format
            Unit unt2 = "N";                                            //Explicit conversion
            Unit unt3 = Unit.Parse("kg*m/sec^2");                       //Parsing from string - from expression (1)
            Unit unt4 = Unit.Parse("kg*m/s^(ton/kg/500)");              //Parsing from string - from expression (2)
            Unit unt5 = Unit.Parse("kg*m/s^(kg/kg*2)");                 //Parsing from string - from expression (3)
            Unit unt6 = Unit.Parse("kg*m") / (Unit.Parse("sec") ^ 2);   //Parsing from string - from expression (4)

            Unit kg = Unit.Parse("kg");
            Unit m = Unit.Parse("m");
            Unit sec = Unit.Parse("sec");

            Unit unt7 = kg * m / (sec ^ 2);                             //Evaluating thro runtime

            Debug.Assert(unt0 == unt1 && unt1 == unt2 && unt2 == unt3 && unt3 == unt4 && unt4 == unt5 && unt5 == unt6 && unt6 == unt7);

            Unit unt8 = Unit.Parse("kg*m/s^(kg)");		                //will raise error, a unit cannot be placed in power

            //In Action I:
            Measurable meu0 = Measurable.Parse("100 N");
            Measurable meu1 = "100 N";
            Measurable meu2 = new Measurable(unt0, 100);

            Debug.Assert(meu0 == meu1);

            Measurable meu3 = meu0.ConvertTo("kgf");
            Debug.Assert(meu3.Amount == 1000);
            Debug.Assert(meu3.Unit == "kgf");

            //In action II, calculating average acceleration

            Measurable deltax = "100 m";
            Measurable deltaT = "10 sec";
            Measurable scUnit = "2 kg/kg";

            Measurable avgAccl = deltax / (deltaT ^ scUnit);            //which is 1 m/sec^2

            Debug.Assert(avgAccl.Amount == 1);
            Debug.Assert(avgAccl.Unit == "m/  sec^2");


            //In action III: creating new units
            Unit bit = Unit.CreateNew("b");
            Unit B = bit * 8;
            Unit.Register(ref B, "B");
            Unit KB = B * 1024;
            Unit.Register(ref KB, "KB");
            Unit MB = KB * 1024;
            Unit.Register(ref MB, "MB");
            Unit GB = MB * 1024;
            Unit.Register(ref GB, "GB");
            Unit TB = GB * 1024;
            Unit.Register(ref TB, "TB");

            Unit bps = bit / Unit.GetRegisteredUnit("sec");
            Unit.Register(ref bps, "bps");
            Measurable smb = "100 MB/sec";
            Measurable sb = smb.ConvertTo("bps");// 100 MB = 100*1024*1024*8 b = 838860800 b

            Debug.Assert(sb.Amount == 838860800);
            Debug.Assert(sb.Unit == bit / "sec");

        }

        static void Ex2()
        {
            var D = Measurable.Parse("100 m");
            var T = Measurable.Parse("10 sec");

            var V = D/T;

            Console.WriteLine("{0}",V); // will show 10 m/sec

            Console.WriteLine("{0}", V.ConvertTo("foot/hour")); // will show 118109.999 foot/hr
        }
    }
}
